import NNModel from "../../Core/Internals/NNModel";
import { Academy } from "../Academy";
import { ActionSpec } from "../Actuators/ActionSpec";
import { ActionBuffers } from "../Actuators/IActionReceiver";
import { IActuator } from "../Actuators/IActuator";
import { AgentInfo } from "../Agent";
import { ModelRunner } from "../Inference/ModelRunner";
import { ISensor } from "../Sensors/ISensor";
import { IPolicy } from "./IPolicy";

/**
 * 在哪里执行（perform）推理（inference）
 */
export enum InferenceDevice {
	/**
	 * 默认推理，
	 */
	Default = 0,

	/**
	 *
	 */
	GPU = 1,

	Burst = 2,

	CPU = 3,

}


export class BarracudaPolicy implements IPolicy {
	private _modelRunner: ModelRunner;
	private _lastActionBuffer: ActionBuffers = ActionBuffers.empty();

	private _agentId: number = 0;
	private _deterministicInference: boolean = false;

	private _sensorShapes: number[][] = [];
	private _actionSpec: ActionSpec;

	private _behaviorName: string;

	private _actuators: IActuator[] = [];
	private _analyticsSent: boolean = false;

	constructor(
		actionSpec: ActionSpec,
		actuators: IActuator[],
		model: NNModel,
		inferenceDevice: InferenceDevice,
		behaviorName: string,
		deterministicInference = false
	) {
		const modelRunner = Academy.instance.getOrCreateModelRunner(
			model,
			actionSpec,
			inferenceDevice,
			deterministicInference
		);
		this._modelRunner = modelRunner;
		this._behaviorName = behaviorName;
		this._actionSpec = actionSpec;
		this._actuators = actuators;
		this._deterministicInference = deterministicInference;
	}

	public requestDecision(info: AgentInfo, sensors: ISensor[]): void {
		this.sendAnalytics(sensors);
		this._agentId = info.episodeId;
		this._modelRunner?.putObservations(info, sensors);
	}

	private sendAnalytics(sensors: ISensor[]): void {
		if (!this._analyticsSent) {
			this._analyticsSent = true;
			// Analytics.InferenceAnalytics.InferenceModelSet(
			// 	this._modelRunner.Model,
			// 	this._behaviorName,
			// 	this._modelRunner.InferenceDevice,
			// 	sensors,
			// 	this._actionSpec,
			// 	this._actuators
			// );
		}
	}

	public decideAction(): ActionBuffers {
		if (this._modelRunner == null) {
			this._lastActionBuffer = ActionBuffers.empty();
		} else {
			this._modelRunner?.decideBatch();
			this._lastActionBuffer = this._modelRunner.getAction(this._agentId);
		}
		return this._lastActionBuffer;
	}

	public dispose(): void {
		// Dispose implementation
	}
}


